package com.junrry.communication

import android.annotation.SuppressLint
import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.hardware.usb.UsbDevice
import android.hardware.usb.UsbDeviceConnection
import android.hardware.usb.UsbManager
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.activity.ComponentActivity
import com.hoho.android.usbserial.driver.UsbSerialDriver
import com.hoho.android.usbserial.driver.UsbSerialPort
import com.hoho.android.usbserial.driver.UsbSerialProber
import com.junrry.communication.ktx.CustomGlobalScope
import com.junrry.communication.ktx.io
import com.junrry.communication.ktx.ui
import com.junrry.communication.databinding.ActivityPcBinding
import com.junrry.communication.util.GPSDataUtils
import java.io.IOException

private const val TAG = "GPSActivity_LJM"

class GPSActivity : ComponentActivity() {

    private lateinit var binding: ActivityPcBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityPcBinding.inflate(layoutInflater)
        setContentView(binding.root)
        registerUsbReceiver()

        initListener()

        initUsbManager()
    }

    @SuppressLint("UnspecifiedRegisterReceiverFlag")
    private fun registerUsbReceiver() {
        val filter = IntentFilter(ACTION_USB_PERMISSION)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            registerReceiver(usbReceiver, filter, RECEIVER_EXPORTED)
        } else {
            registerReceiver(usbReceiver, filter)
        }
    }

    private fun initUsbManager() {
        manager = getSystemService(USB_SERVICE) as UsbManager

        val availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(manager)
        if (availableDrivers.isEmpty()) {
            return
        }

        val str = StringBuilder()
        val permissionIntent = PendingIntent.getBroadcast(
            this, 0,
            Intent(ACTION_USB_PERMISSION), 0
        )
        availableDrivers.forEach { d ->
            Log.d(TAG, "device = ${d.device.vendorId}  ${d.device.productId}")
            str.append("device = ${d.device.vendorId}  ${d.device.productId}\n")
            if (d.device.vendorId == 6790 && d.device.productId == 29987) {
                driver = d
                usbDevice = driver.device

                manager.requestPermission(usbDevice, permissionIntent)
            }
        }

        binding.tvDevice.text = str.toString()
    }

    override fun onDestroy() {
        super.onDestroy()
        unregisterReceiver(usbReceiver)
        port?.close()
    }

    private fun initListener() {
        binding.btnSend.setOnClickListener {
            if (binding.etSend.text.isNullOrEmpty()) {
                Toast.makeText(this, "请输入发送内容", Toast.LENGTH_SHORT).show()
                return@setOnClickListener
            }
            if (driver == null) {
                Toast.makeText(this, "请连接设备", Toast.LENGTH_SHORT).show()
                return@setOnClickListener
            }
            CustomGlobalScope.io {
                sendSDK(binding.etSend.text.toString().trim())
            }
        }
    }

    private val ACTION_USB_PERMISSION = "android.permission.USB_PERMISSION"
    lateinit var usbDevice: UsbDevice
    lateinit var connection: UsbDeviceConnection
    lateinit var manager: UsbManager
    lateinit var driver: UsbSerialDriver
    var port: UsbSerialPort? = null


    private val usbReceiver = object : BroadcastReceiver() {

        override fun onReceive(context: Context, intent: Intent) {
            if (ACTION_USB_PERMISSION == intent.action) {
                val device: UsbDevice? = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE)

                if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                    initConnectionSDK()
                } else {
                    Log.d(TAG, "permission denied for device $device")
                }
            }
        }
    }


    private fun initConnectionSDK() {
        connection = manager.openDevice(usbDevice)
        if (connection != null) {
            try {
                port = driver.ports[0]
                port?.open(connection);
                //设置串口的波特率、数据位，停止位，校验位
                port?.setParameters(9600, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE);
                val buffer = ByteArray(1024) // 数据缓存
                val str = StringBuilder()
                CustomGlobalScope.io {
                    // 循环读取数据
                    while (true) {
                        val numBytesRead = port?.read(buffer, 1000)
                        if (numBytesRead!! > 0) {
                            // 处理接收到的数据
                            val receivedData = String(buffer, 0, numBytesRead)
                            Log.d(TAG, "USB Data" + receivedData)
                            if (receivedData.isNullOrEmpty()) {
                                continue
                            }
                            str.append(receivedData + "\n")
                            CustomGlobalScope.ui {
                                binding.tvReceiver.text = str.toString()
                                GPSDataUtils.getGGA(GPSDataUtils.DATA)
                            }
                        }
                    }
                }
            } catch (e: Exception) {
                // Deal with error.
            } finally {

            }
        }
    }

    private fun sendSDK(msg: String) {
        try {
            port?.write(msg.toByteArray(), 1000)
        } catch (e: IOException) {
            // Deal with error.
        }
    }

    /**
     * 数据
    $GNGGA,092120.000,3616.19583,N,12020.14383,E,1,05,8.9,68.6,M,0.0,M,,*4E
    $GNGLL,3616.19583,N,12020.14383,E,092120.000,A,A*47
    $GPGSA,A,3,13,19,30,194,,,,,,,,,16.2,8.9,13.5*04
    $BDGSA,A,3,14,,,,,,,,,,,,16.2,8.9,13.5*25
    $GPGSV,3,1,12,05,44,265,,06,43,090,,07,08,084,,12,15,243,20*77
    $GPGSV,3,2,12,13,24,182,32,19,16,155,34,20,69,330,,25,11,277,*74
    $GPGSV,3,3,12,29,17,319,,30,07,117,28,194,16,175,31,199,,,21*4D
    $BDGSV,1,1,02,03,,,29,14,17,222,27*56
    $GNRMC,092120.000,A,3616.19583,N,12020.14383,E,0.00,166.25,150425,,,A*71
    $GNVTG,166.25,T,,M,0.00,N,0.00,K,A*25
    $GNZDA,092120.000,15,04,2025,00,00*45
    $GPTXT,01,01,01,ANTENNA OPEN*25
     */
    /**
     * $GNGGA,091311.000,3616.17939,N,12020.15004,E,1,04,16.8,29.1,M,0.0,M,,*7E
     * 全球定位信息($**GGA)
     * 其标准格式为：＄GPGGA，(1)，(2)，(3)，(4)，(5)，(6)，(7)，(8)，(9)，M，(10)，M，(11)，(12)＊hh(CR)(LF) 　
     * 各部分所对应的含义为： 　　
     * (1)定位UTC时间：09时03分11秒　　
     * (2)纬度(格式ddmm.mmmm:即dd度，mm.mmmm分)；　　
     * (3)N/S(北纬或南纬)：北纬36度16.17939分；　　
     * (4)经度(格式dddmm.mmmm：即ddd度，mm.mmmm分)；　　
     * (5)E/W(东经或西经)：东经120度20.15004分；　　
     * (6)质量因子(0=没有定位，1=实时GPS，2=差分GPS)：1=实时GPS；　　
     * (7)可使用的卫星数(0～8)：可使用的卫星数=07；　　
     * (8)水平精度因子(1.0～99.9)；水平精度因子=1.4；　　
     * (9)天线高程(海平面，－9999.9～99999.9，单位：m)；天线高程=76.2m); 　　
     * (10)大地椭球面相对海平面的高度(－999.9～9999.9，单位：m):－7.0m; 　　
     * (11)差分GPS数据年龄，实时GPS时无:无; 　　
     * (12)差分基准站号(0000～1023)，实时GPS时无:无; 　　
     * ＊总和校验域；　　
     * hh 总和校验数:65 　　
     * (CR)(LF)回车，换行。 　　
     *
     * $GNGLL,3616.17939,N,12020.15004,E,091311.000,A,A*4A
     * 地理定位信息($**GLL)
     *
     *
     * $GPGSA,A,3,13,19,30,194,,,,,,,,,23.2,16.8,16.0*3C
     * $BDGSA,A,3,,,,,,,,,,,,,23.2,16.8,16.0*18
     * 当前卫星信息($**GSA)
     * $GPGSA,<1>,<2>,<3>,<3>,,,,,<3>,<3>,<3>,<4>,<5>,<6>*<7>
     *
     * <1>模式 ：M = 手动， A = 自动。
     * <2>定位型式 1 = 未定位， 2 = 二维定位， 3 = 三维定位。
     * <3>PRN 数字：01 至 32 表天空使用中的卫星编号，最多可接收12颗卫星信息。
     * <4> PDOP位置精度因子(0.5~99.9)
     * <5> HDOP水平精度因子(0.5~99.9)
     * <6> VDOP垂直精度因子(0.5~99.9)
     * <7> Checksum.(检查位).
     *
     * $GPGSV,1,1,04,13,20,182,35,19,20,154,34,30,05,120,31,194,17,175,38*48
     * $BDGSV,1,1,01,03,,,30*69
     * 可视卫星状态输出语句($**GSV) 　 　　
     * 标准格式：$**GSV，(1)，(2)，(3)，(4)，(5)，(6)，(7)，…(4),(5)，(6)，(7)*hh(CR)(LF) 　　
     * 各部分含义为： 　　
     * (1)总的GSV语句电文数；2;
     * (2)当前GSV语句号:1; 　　
     * (3)可视卫星总数:08; 　　
     * (4)卫星号:06; 　　
     * (5)仰角(00～90度):33度; 　　
     * (6)方位角(000～359度):240度; 　　
     * (7)信噪比(00～99dB):45dB(后面依次为第10，16，17号卫星的信息); 　　
     * *总和校验域；　　
     * hh 总和校验数:78; 　　
     * (CR)(LF)回车，换行。 　　
     * 注：每条语句最多包括四颗卫星的信息，每颗卫星的信息有四个数据项，即：　　
     * (4)－卫星号，(5)－仰角，(6)－方位角，(7)－信噪比。
     *
     * $GNRMC,091311.000,A,3616.17939,N,12020.15004,E,0.00,166.25,150425,,,A*7C
     * 推荐最小定位信息($**RMC)
     * $**RMC,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,<10>,<11>,<12>*hh
     * <1> UTC时间，hhmmss(时分秒)格式
     * <2> 定位状态，A=有效定位，V=无效定位
     * <3> 纬度ddmm.mmmm(度分)格式(前面的0也将被传输)
     * <4> 纬度半球N(北半球)或S(南半球)
     * <5> 经度dddmm.mmmm(度分)格式(前面的0也将被传输)
     * <6> 经度半球E(东经)或W(西经)
     * <7> 地面速率(000.0~999.9节，前面的0也将被传输)
     * <8> 地面航向(000.0~359.9度，以真北为参考基准，前面的0也将被传输)
     * <9> UTC日期，ddmmyy(日月年)格式
     * <10> 磁偏角(000.0~180.0度，前面的0也将被传输)
     * <11> 磁偏角方向，E(东)或W(西)
     * <12> 模式指示(仅NMEA0183 3.00版本输出，A=自主定位，D=差分，E=估算，N=数据无效)
     *
     * $GNVTG,166.25,T,,M,0.00,N,0.00,K,A*25
     * 地面速度信息($**VTG)
     * $GPVTG,<1>,T,<2>,M,<3>,N,<4>,K,<5>*hh
     * <1> 以真北为参考基准的地面航向(000~359度，前面的0也将被传输)
     * <2> 以磁北为参考基准的地面航向(000~359度，前面的0也将被传输)
     * <3> 地面速率(000.0~999.9节，前面的0也将被传输)
     * <4> 地面速率(0000.0~1851.8公里/小时，前面的0也将被传输)
     * <5> 模式指示(仅NMEA0183 3.00版本输出，A=自主定位，D=差分，E=估算，N=数据无效)
     *
     * $GNZDA,091311.000,15,04,2025,00,00*46
     * 输出UTC时间($**ZDA)
     * $**ZDA,<1>,<2>,<3>,<4>,<5>,<6>*hh
     * <1> UTC时间，hhmmss(时分秒)格式
     * <2> 日00~31
     * <3> 月00~12
     * <4> 年0000~9999
     * <5> 地方时与世界时之差
     * <6>
     *
     * $GPTXT,01,01,01,ANTENNA OPEN*25
     *
     *
     * $GPGNS,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>.<9>,<10>,<11>,<12>,<13>*<14>
     * GNS定位数据
     * <1>UTC时间:定位时间 hhmmss.ss
     * <2>纬度: ddmm.mmmmm-
     * <3>南纬北纬: 北纬N，S南纬
     * <4>经度:dddmm.mmmmm
     * <5>东经西经: 东经E，西经W
     * <6>定位模式:N-未定位，A-已定位，D-普通差分定位，P-高精度定位，R-RTK定位固定解，F-RTK定位浮点解，E-估算值，M-注入位置;S-模拟输入
     * <7>定位P星:参与定位卫星
     * <8>HDOP:水平精度因子，0-500
     * <9>海拔: 单位:米
     * <10>大地水准面: 地球球面相对人地水准面的高度
     * <11>差异数据时间: GN开头时为空
     * <12>基准站ID: GN开头时为空
     * <13>导航状态 C=告警，S=安全，U=不安全，V=无效
     * <14>校验
     */

}